package com.example.wifi;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;


import com.android.dx.stock.ProxyBuilder;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

import static android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION;
import static android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION;
import static android.net.wifi.WifiManager.SUPPLICANT_STATE_CHANGED_ACTION;
import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION;

public class MainActivity extends AppCompatActivity {

    private static WifiManager wifiManager;
    private LocationManager locationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
        }
        wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        registerWifiReceiver();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        for(int i=0;i<permissions.length;i++){
            Log.e("androidLog",permissions[i]+"=="+grantResults[i]);
        }
    }

    private void registerWifiReceiver(){
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(SCAN_RESULTS_AVAILABLE_ACTION);
        intentFilter.addAction(NETWORK_STATE_CHANGED_ACTION);
        intentFilter.addAction(WIFI_STATE_CHANGED_ACTION);
        intentFilter.addAction(SUPPLICANT_STATE_CHANGED_ACTION);
        registerReceiver(new WifiStateReceiver(),intentFilter);
    }


    private class WifiStateReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()){
                case SCAN_RESULTS_AVAILABLE_ACTION:
//                    getWifiScanResult();
                    break;
                case NETWORK_STATE_CHANGED_ACTION:
                    getNetworkState(intent);
                    break;
                case WIFI_STATE_CHANGED_ACTION:
                    getWifiState(intent);
                    break;
                case SUPPLICANT_STATE_CHANGED_ACTION:
                    getWifiConnResult(intent);
                    break;
            }
        }
    }

    private void getWifiScanResult(){

        List<ScanResult> scanResultList = wifiManager.getScanResults();
        if(scanResultList.size()==0){
//            wifiManager.startScan();
        }
        Log.e("androidLog","scanResultList.size="+scanResultList.size());
        for (ScanResult scanResult:scanResultList){
            Log.e("androidLog",scanResult.SSID+":"+scanResult.level);
        }
    }


    private void getWifiState(Intent intent){
        int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,0);
        switch (state){
            case WifiManager.WIFI_STATE_DISABLED:
                Log.e("androidLog","WIFI_STATE_DISABLED");
                break;
            case WifiManager.WIFI_STATE_DISABLING:
                Log.e("androidLog","WIFI_STATE_DISABLING");
                break;
            case WifiManager.WIFI_STATE_ENABLED:
                Log.e("androidLog","WIFI_STATE_ENABLED");
                wifiManager.startScan();
                break;
            case WifiManager.WIFI_STATE_ENABLING:
                Log.e("androidLog","WIFI_STATE_ENABLING");
                break;
            case WifiManager.WIFI_STATE_UNKNOWN:
                Log.e("androidLog","WIFI_STATE_UNKNOWN");
                break;
        }
    }

    public void getWifiConnResult(Intent intent){
        int linkWifiResult = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 123);
        if (linkWifiResult == WifiManager.ERROR_AUTHENTICATING) {
            Log.e("androidLog","ERROR_AUTHENTICATING");
        }
    }

    public void getNetworkState(Intent intent){
        Parcelable parcelable = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
        if (null != parcelable) {
            NetworkInfo.DetailedState detailedState = ((NetworkInfo)parcelable).getDetailedState();
            switch (detailedState){
                case IDLE:
                    Log.e("androidLog","NETWORK_STATE_IDLE");
                    break;
                case AUTHENTICATING:
                    Log.e("androidLog","NETWORK_STATE_AUTHENTICATING");
                    break;
                case CONNECTING:
                    Log.e("androidLog","NETWORK_STATE_CONNECTING");
                    //开始连接WIFI时会触发
                    break;
                case CONNECTED:
                    Log.e("androidLog","NETWORK_STATE_CONNECTED");
                    //连接WIFI成功时会触发
                    break;
                case DISCONNECTING:
                    Log.e("androidLog","NETWORK_STATE_DISCONNECTING");
                    break;
                case DISCONNECTED:
                    Log.e("androidLog","NETWORK_STATE_DISCONNECTED");
                    //连接WIFI失败时会触发
                    break;
            }
        }
    }

    public void btnOpenWifi(View view) {
        if(!wifiManager.isWifiEnabled()){
            Log.e("androidLog","OpenWifi");
            wifiManager.setWifiEnabled(true);
        }
    }

    public void btnCloseWifi(View view) {
        if(wifiManager.isWifiEnabled()){
            Log.e("androidLog","CloseWifi");
            wifiManager.setWifiEnabled(false);
        }
    }

    public void btnOpenLocation(View view) {
        if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);
        }
    }

    public void btnCloseLocation(View view) {
    }

    public void btnScanWifi(View view) {
        getWifiScanResult();
    }


    public void btnConnRightWifi(View view) {
        WifiConfiguration wifiConfiguration = createWifiInfo("Ctyon1","ctyon2016",getCipherType("Ctyon1"));
        int netId = wifiManager.addNetwork(wifiConfiguration);
        Log.e("androidLog","netId="+netId);
        wifiManager.enableNetwork(netId,true);
    }

    public void btnConnWrongWifi(View view) {
        WifiConfiguration wifiConfiguration = createWifiInfo("Ctyon1","ctyon2017",getCipherType("Ctyon1"));
        int netId = wifiManager.addNetwork(wifiConfiguration);
        Log.e("androidLog","netId="+netId);
        wifiManager.enableNetwork(netId,true);
    }

    public void btnOpenAp(View view) {
        startTethering();
    }

    /**
     * 获取ssid的加密方式
     */
    public static WifiCipherType getCipherType(String ssid) {
        if (wifiManager == null) {
            return null;
        }
        List<ScanResult> list = wifiManager.getScanResults();

        for (ScanResult scResult : list) {

            if (!TextUtils.isEmpty(scResult.SSID) && scResult.SSID.equals(ssid)) {
                String capabilities = scResult.capabilities;
                if (!TextUtils.isEmpty(capabilities)) {

                    if (capabilities.contains("WPA")
                            || capabilities.contains("wpa")) {
                        Log.e("wifidemo", "wpa");
                        return WifiCipherType.WIFICIPHER_WPA;
                    } else if (capabilities.contains("WEP")
                            || capabilities.contains("wep")) {
                        Log.e("wifidemo", "wep");
                        return WifiCipherType.WIFICIPHER_WEP;
                    } else {
                        Log.e("wifidemo", "no");
                        return WifiCipherType.WIFICIPHER_NOPASS;
                    }
                }
            }
        }
        return WifiCipherType.WIFICIPHER_INVALID;
    }

    // 定义几种加密方式，一种是WEP，一种是WPA，还有没有密码的情况
    public enum WifiCipherType {
        WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
    }

    public WifiConfiguration createWifiInfo(String SSID, String Password, WifiCipherType Type) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + SSID + "\"";
        // config.SSID = SSID;
        // nopass
        if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
            // config.wepKeys[0] = "";
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            // config.wepTxKeyIndex = 0;
        } else if (Type == WifiCipherType.WIFICIPHER_WEP) {// wep
            if (!TextUtils.isEmpty(Password)) {
                if (isHexWepKey(Password)) {
                    config.wepKeys[0] = Password;
                } else {
                    config.wepKeys[0] = "\"" + Password + "\"";
                }
            }
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.wepTxKeyIndex = 0;
        } else if (Type == WifiCipherType.WIFICIPHER_WPA) {// wpa
            config.preSharedKey = "\"" + Password + "\"";
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            config.status = WifiConfiguration.Status.ENABLED;
        }
        return config;
    }

    private static boolean isHexWepKey(String wepKey) {
        final int len = wepKey.length();
        // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
        if (len != 10 && len != 26 && len != 58) {
            return false;
        }
        return isHex(wepKey);
    }

    private static boolean isHex(String key) {
        for (int i = key.length() - 1; i >= 0; i--) {
            final char c = key.charAt(i);
            if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'
                    && c <= 'f')) {
                return false;
            }
        }
        return true;
    }

    private  void startTethering() {
        ConnectivityManager connectivityManager = ((ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE));
        try {
            Class classOnStartTetheringCallback = Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");
            Method startTethering = connectivityManager.getClass().getDeclaredMethod("startTethering", int.class, boolean.class, classOnStartTetheringCallback);
            Object proxy = ProxyBuilder.forClass(classOnStartTetheringCallback).handler(new InvocationHandler() {
                @Override
                public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                    return null;
                } }).build();
            startTethering.invoke(connectivityManager, 0, false, proxy);
        } catch (Exception e) {
            Log.e("androidLog","打开热点失败=="+e.getMessage());
            e.printStackTrace();
        }
    }

}
